import logging
import os
import sys
import argparse
import datetime

basedir = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, basedir)

GLOBAL_NOW_TIME = datetime.datetime.now().strftime("%Y%m%d%H%M%S")

try:
    from .mysql_utils import sql_execute
    from .interactive_with_dbpt import get_proxysql_admin_password
    from .interactive_with_dbpt import get_proxysql_instance_info_by_mysql_instance_info
    from .interactive_with_dbpt import send_alert
    from .os_utils import get_host_ip
    from .os_utils import write_json
    from .os_utils import read_json
except Exception:
    from mysql_utils import sql_execute
    from interactive_with_dbpt import get_proxysql_admin_password
    from interactive_with_dbpt import get_proxysql_instance_info_by_mysql_instance_info
    from interactive_with_dbpt import send_alert
    from os_utils import get_host_ip
    from os_utils import write_json
    from os_utils import read_json

log = logging.getLogger(__name__)

log_dir = "{basedir}/fail_over_log/".format(basedir=basedir)

if not os.path.exists(log_dir):
    os.makedirs(log_dir)

log_name = "{log_dir}/orchestrator_failover_processes-{now_time}.log".format(log_dir=log_dir,
                                                                             now_time=GLOBAL_NOW_TIME)
formatter = logging.basicConfig(filename=log_name,
                                level=logging.INFO,
                                format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
                                datefmt='%a, %d %b %Y %H:%M:%S')

parser = argparse.ArgumentParser(description='mysql backup command line .',
                                 usage=None,
                                 add_help=True)
parser.add_argument('--host', '-i', type=str, help='host of mysql fail instance', required=True)
parser.add_argument('--port', '-p', type=int, help='port of mysql fail instance', required=True)
parser.add_argument('--command', '-c', type=str, help='command', required=False, nargs='?', const='')
args = parser.parse_args()
mysql_fail_host = args.host
mysql_fail_port = args.port
command = args.command


def get_proxysql_host_port(mysql_host, mysql_port):
    return get_proxysql_instance_info_by_mysql_instance_info(mysql_host=mysql_host, mysql_port=mysql_port)


def get_proxysql_cluster_password(proxysql_host, proxysql_port):
    return get_proxysql_admin_password(proxysql_host, proxysql_port)


def proxysql_mysql_servers_info_get(mysql_config_dict):
    backup_mysql_servers_sql = "select * from  mysql_servers  ;"

    mysql_servers_backup_info = sql_execute(sql_to_execute=backup_mysql_servers_sql,
                                            mysql_config_dict=mysql_config_dict)
    log.info("Table mysql_servers backup info: {mysql_servers_backup_info}".format(
        mysql_servers_backup_info=mysql_servers_backup_info))

    backup_runtime_mysql_servers_sql = "select * from  runtime_mysql_servers ;"
    runtime_mysql_servers_backup_info = sql_execute(sql_to_execute=backup_runtime_mysql_servers_sql,
                                                    mysql_config_dict=mysql_config_dict)
    log.info("Table runtime_mysql_servers_backup_info backup info: {runtime_mysql_servers_backup_info}".format(
        runtime_mysql_servers_backup_info=runtime_mysql_servers_backup_info))


def proxysql_mysql_servers_info_backup(mysql_host, mysql_port, mysql_config_dict):
    # now_time = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
    now_time = GLOBAL_NOW_TIME
    recovery_directory = "{basedir}/recovery_info/instance_backup_info_on_proxysql".format(basedir=basedir)
    if not os.path.exists(recovery_directory):
        os.makedirs(recovery_directory)

    filename = "{recovery_directory}/{mysql_host}-{mysql_port}-{now_time}.json".format(
        recovery_directory=recovery_directory,
        mysql_host=mysql_host,
        mysql_port=mysql_port,
        now_time=now_time)
    backup_dict_info_for_special_instance = "select * from mysql_servers " \
                                            "where hostname = '{mysql_host}' and port={mysql_port} " \
                                            "and hostgroup_id = 3 ; ".format(mysql_host=mysql_host,
                                                                             mysql_port=mysql_port)
    mysql_servers_backup_info = sql_execute(sql_to_execute=backup_dict_info_for_special_instance,
                                            mysql_config_dict=mysql_config_dict)
    write_json(filename=filename, json_to_write={"mysql_info_in_proxysql": mysql_servers_backup_info})


def mysql_route_down(fail_host, fail_port):
    proxysql_username = "cluster"

    proxysql_host, proxysql_port = get_proxysql_host_port(fail_host, fail_port)
    log.info("Now get the proxysql instance info.")
    if proxysql_host is None or proxysql_port is None:
        log.error("Can't not find proxysql information of instance: {fail_host}:{fail_port}".format(
            fail_host=fail_host, fail_port=fail_port))
        sys.exit(1)
    log.info("Instance of proxysql :{proxysql_host}:{proxysql_port}".format(proxysql_host=proxysql_host,
                                                                            proxysql_port=proxysql_port))
    proxysql_password = get_proxysql_cluster_password(proxysql_host, proxysql_port)
    if proxysql_password is None:
        log.error("Can't get password of proxysql instance: {proxysql_host}:{proxysql_port}".format(
            proxysql_host=proxysql_host, proxysql_port=proxysql_port))
        sys.exit(1)

    mysql_config_dict = {"database_name": None, "host": proxysql_host, "port": proxysql_port,
                         "password": proxysql_password,
                         "username": proxysql_username}

    proxysql_mysql_servers_info_backup(mysql_host=fail_host, mysql_port=fail_port, mysql_config_dict=mysql_config_dict)

    proxysql_mysql_servers_info_get(mysql_config_dict)
    # offline_hard_sql = """ update mysql_servers set status = 'OFFLINE_HARD'
    # where hostname = '{fail_host}' and port = {fail_port} ; """.format(
    #     fail_host=fail_host, fail_port=fail_port)
    offline_sql = """delete from  mysql_servers 
    where hostname = '{fail_host}' and port = {fail_port} ; """.format(
        fail_host=fail_host, fail_port=fail_port)
    sql_execute(sql_to_execute=offline_sql, mysql_config_dict=mysql_config_dict)

    load_to_runtime_sql = "LOAD MYSQL SERVERS TO RUNTIME;"
    sql_execute(sql_to_execute=load_to_runtime_sql, mysql_config_dict=mysql_config_dict)

    load_to_disk_sql = "SAVE MYSQL SERVERS TO DISK;"
    sql_execute(sql_to_execute=load_to_disk_sql, mysql_config_dict=mysql_config_dict)
    proxysql_mysql_servers_info_get(mysql_config_dict)


def main():
    local_host_ip = get_host_ip()
    log.info("command is %s" % command)
    if command == "graceful-master-takeover":
        log.info("Now manual switch the instance: {mysql_fail_host}:{mysql_fail_port}! \n"
                 "We do nothing here. ".format(mysql_fail_host=mysql_fail_host,
                                               mysql_fail_port=mysql_fail_port,
                                               ))
        return 0
    log.info(
        "Fail instance info :{mysql_fail_host}:{mysql_fail_port}".format(mysql_fail_host=mysql_fail_host,
                                                                         mysql_fail_port=mysql_fail_port))
    send_alert("CRITICAL: Detect failed instance: {mysql_fail_host}:{mysql_fail_port}! \n"
               "Now start the the failover process. \n "
               "Please check log: {log_name} on orchestrator "
               "host: {orchestrator_host} . ".format(mysql_fail_host=mysql_fail_host, mysql_fail_port=mysql_fail_port,
                                                     orchestrator_host=local_host_ip, log_name=log_name), 1)
    mysql_route_down(fail_host=mysql_fail_host, fail_port=mysql_fail_port)


if __name__ == "__main__":
    sys.exit(main())
